package com.glodon.paas.account.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Service;

import com.glodon.paas.account.api.bean.Address;
import com.glodon.paas.account.api.bean.Company;
import com.glodon.paas.account.api.bean.Consumer;
import com.glodon.paas.account.api.bean.Contact;
import com.glodon.paas.account.api.bean.OAuth2Token;
import com.glodon.paas.account.api.bean.OAuthToken;
import com.glodon.paas.account.api.bean.User;
import com.glodon.paas.account.biz.UserBiz;
import com.glodon.paas.account.dao.domain.AddressEntity;
import com.glodon.paas.account.dao.domain.AvatarEntity;
import com.glodon.paas.account.dao.domain.CompanyEntity;
import com.glodon.paas.account.dao.domain.ContactEntity;
import com.glodon.paas.account.dao.domain.OAuthTokenEntity;
import com.glodon.paas.account.dao.domain.ScopeEntity;
import com.glodon.paas.account.dao.domain.UserEntity;
import com.glodon.paas.account.service.UserService;
import com.glodon.paas.dto.DataTansitionObject;
import com.glodon.paas.exception.PaasServerExceptionFactory;
import com.glodon.paas.exception.i18n.ErrorCode;
import com.glodon.paas.util.SimpleBeanConverter;

@Service("userService")
public class UserServiceImpl implements UserService {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
	
	@Autowired
	private UserBiz userBiz;

	@Override
	public User registerAccount(String accountName, Integer accountType, String password, Integer status){
		UserEntity udb = userBiz.registerAccount(accountName, accountType, password, status);
		return UserEntity.getDto(udb, false);
	}
	
	@Override
	public void activeUser(String userId, String accountName, Integer accountType, String password) {
		userBiz.activeUser(userId, accountName, accountType, password);
	}
	
	@Override
	public void updateUser(User user) {
		if(user == null || StringUtils.isEmpty(user.getId())){
			throw PaasServerExceptionFactory.validateException("user is empty", null);
		}
		UserEntity dbUser = userBiz.getUser(user.getId());
		if(dbUser == null){
			throw PaasServerExceptionFactory.notFoundException("can not find user["+user.getId()+"]", null).setErrorCode(ErrorCode.USER_NOT_EXIST);
		}
		
		if (user.getRealname()  != null) {
			dbUser.setRealname(user.getRealname());
		}
		if (user.getNickname() != null) {
			dbUser.setNickname(user.getNickname());
		}
		if (user.getGender() != null) {
			dbUser.setGender(user.getGender());
		}
		if (user.getBirthday() != null) {
			dbUser.setBirthday(user.getBirthday());
		}
		
		dbUser.setAddressId(saveAddress(user.getId(),user.getAddress(), dbUser.getAddressId()));
		dbUser.setContactId(saveContact(user.getId(),user.getContact(), dbUser.getContactId()));
		dbUser.setCompanyId(saveCompany(user.getId(),user.getCompany(), dbUser.getCompanyId()));

		userBiz.updateUser(dbUser);
		LOGGER.debug("update User["+user.getId()+"] success.");
	}
	
	private String saveAddress(String userId, Address addr, String addressId){
		if (addr != null) {
			addr.setUserId(userId);
			AddressEntity dbAddr=null;
			if(!StringUtils.isEmpty(addressId)){
				dbAddr = userBiz.getAddress(addressId);
			}
			if (dbAddr == null) {
				addressId = userBiz.insertAddress(SimpleBeanConverter.converte(addr, AddressEntity.class));
			} else {
				dbAddr = SimpleBeanConverter.converte(addr, AddressEntity.class);
				dbAddr.setId(addressId);
				userBiz.updateAddress(dbAddr);
			}
		}
		return addressId;
	}
	
	private String saveContact(String userId, Contact contact, String contactId){
		if (contact != null) {
			contact.setUserId(userId);
			ContactEntity dbContact = null;
			if(!StringUtils.isEmpty(contactId)){
				dbContact = userBiz.getContact(contactId);
			}
			if (dbContact == null) {
				dbContact = SimpleBeanConverter.converte(contact, ContactEntity.class);
				dbContact.setAddressId(saveAddress(userId, contact.getAddress(), dbContact.getAddressId()));
				contactId = userBiz.insertContact(dbContact);
			} else {
				String addressId = saveAddress(userId,contact.getAddress(), dbContact.getAddressId());
				dbContact = SimpleBeanConverter.converte(contact, ContactEntity.class);
				dbContact.setAddressId(addressId);
				dbContact.setId(contactId);
				userBiz.updateContact(dbContact);
			}
		}
		return contactId;
	}
	
	private String saveCompany(String userId, Company company, String companyId){
		if (company != null) {
			company.setUserId(userId);
			CompanyEntity dbCompany = null;
			if(!StringUtils.isEmpty(companyId)){
				dbCompany = userBiz.getCompany(companyId);
			}
			
			if (dbCompany == null) {
				dbCompany = SimpleBeanConverter.converte(company, CompanyEntity.class);
				dbCompany.setAddressId(saveAddress(userId, company.getAddress(), dbCompany.getAddressId()));
				companyId = userBiz.insertCompany(dbCompany);
			} else {
				String addressId = saveAddress(userId, company.getAddress(), dbCompany.getAddressId());
				dbCompany = SimpleBeanConverter.converte(company, CompanyEntity.class);
				dbCompany.setAddressId(addressId);
				dbCompany.setId(companyId);
				userBiz.updateCompany(dbCompany);
			}
		}
		return companyId;
	}

	@Override
	public boolean checkEmailExist(String email) {
		return userBiz.checkEmailExist(email);
	}

	@Override
	public void cancelAuthorizationApp(String tokenId) {
		userBiz.deleteToken(tokenId);
		LOGGER.debug("canceled the authorization Token[id:"+tokenId+"]");
	}

	@Override
	public User getUserByAccountName(String accountName,Integer accountType, Integer status) {
		return UserEntity.getDto(userBiz.getUserByAccountName(accountName,accountType,status), false);
	}
	
	@Override
	public User getUserById(String userId) {
		return UserEntity.getDto(userBiz.getUser(userId), false);
	}
	
	@Override
	public User getUserInfoById(String userId) {
		return UserEntity.getDto(userBiz.getUser(userId), true);
	}

	@Override
	public List<OAuthToken> getAccessTokens(String userId){
		return SimpleBeanConverter.converte(userBiz.getAccessTokens(userId),OAuthToken.class);
	}

	@Override
	public List<DataTansitionObject> getAuthorizatedApps(String userId) {
		List<OAuthTokenEntity> tokens = userBiz.getAccessTokens(userId);
		List<DataTansitionObject> datas = new ArrayList<DataTansitionObject>();
		if (tokens != null) {
			for (OAuthTokenEntity token : tokens) {
				DataTansitionObject data = new DataTansitionObject();
				data.setId(token.getValue());
				data.setName(userBiz.getConsumerByKey(token.getConsumerKey()).getDescription());
				datas.add(data);
			}
		}
		return datas;
	}


	@Override
	public List<OAuth2Token> getAuthInfo(String userId) {
		List<OAuth2AccessToken> accessTokens = userBiz.getOAuth2Tokens(userId);
						
		List<OAuth2Token> tokens =  SimpleBeanConverter.converte(accessTokens,OAuth2Token.class);
		
		assert(accessTokens.size() == tokens.size());
		
		for(int i=0;i<tokens.size();i++){			
			String consumerId = userBiz.getConsumerId(accessTokens.get(i));
			tokens.get(i).setConsumerId(consumerId);
		}
		return tokens;
	}
	
	@Override
	public Consumer getConsumerByKey(String key) {
		return SimpleBeanConverter.converte(userBiz.getConsumerByKey(key), Consumer.class);
	}
 
	@Override
	public int saveAvatar(String id, String userId, Integer size, byte[] item) {		
		return userBiz.saveAvatar(id, userId, size, item);
	}
	@Override
	public byte[] getAvatar(String id, String userId, Integer size) {
		AvatarEntity av = userBiz.getAvatar(id, userId, size);
		if(av == null){
			return null;
		}
		return av.getItem();
	}
	@Override
	public int deleteAvatar(String id, String userId, Integer size) {
		return userBiz.deleteAvatar(id, userId, size);
	} 
	public void setUserBiz(UserBiz userBiz) {
        this.userBiz = userBiz;
    }

    @Override
    public void addProjectRole(String id,String userId, String projectId, String roleId,String orgId) {
        userBiz.addProjectRole(id,userId, projectId, roleId,orgId);
    }
	@Override
	public int deleteProjectRole(String userId, String projectId, String roleId,String orgId) {
		return userBiz.deleteProjectRole(userId, projectId, roleId,orgId);
		
	}

	@Override
	public int updateProjectRole(String projectId, String oldeRoleId,
			String newRoleId) {
		return userBiz.updateProjectRole(projectId, oldeRoleId,newRoleId);
	}
    @Override
	public   List<DataTansitionObject> getScopeInfo(String scopes){
    	List<DataTansitionObject> dataList = new ArrayList<DataTansitionObject>();    	
    	List<ScopeEntity> entityList = userBiz.getScope(scopes);    	
    	for(ScopeEntity e : entityList){    		
    		DataTansitionObject data = new DataTansitionObject();
    		data.setId(e.getScopeId());
    		data.setName(e.getScopeDesc());
    		dataList.add(data);
    	}      	
    	return dataList;
    }
    
    @Override
	public  Set<String> getScope(String resourceId){  
    	Set<String> scopes = new HashSet<String>();
    	scopes.add("001");
    	scopes.add("002");
    	scopes.add("003");
    	return scopes;
    }
}